﻿// Inner Fire 游戏引擎库
// IPlayable - 通用播放接口
//
// Copyright (c) 2025 by 尔西大帝. All rights reserved.
//
// 所属层级：应用层(4)
// 用于管理游戏中的动画播放。目前只有这个功能，别搞复杂了。
// 以后可能扩展一个音频。
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2025-04-30

#pragma once

#include <game/animation/animation_blend.h>
#include <game/animation/animation_clip.h>
#include <game/animation/animation_def.h>
#include <glm.hpp>

namespace ifire::game {

enum class PlayableType {
  Empty,  // 表示当前项目为空项目
  Clip,   // 播放单个项目
  Blend,  // 播放一个BlendTree项目
  Audio,  // 播放一个音频（暂时不实现）
  Script, // 播放一个脚本（暂时不实现）
};


/// <summary>
/// 通用的用于描述一个播放项目的东西。在设计时遵守几个要点：
/// 1、因为需要频繁地切换Playable，所以Playable不需要分配内存，而是使用struct值传递。
/// 2、通过Type来决定内部如何运作。其中的每个分支的值被隐藏。
/// </summary>
struct Playable {
public:
  // 默认的空对象
  Playable();
  // 通过Clip初始化项目
  Playable(AnimationClip* clip, PlayMethod loop);
  // 通过Blend初始化项目
  Playable(AnimationBlend* blend, PlayMethod loop);

  // 设置当前的播放帧
  void SetFrame(float frame);
  // 设置当前的播放时间
  void SetTime(float time);
  // 动态计算当前的Frame
  float GetFrame() const;

  // 根据Delta的步进，计算时间
  void AddDeltaTime(float delta_time);

  // 是否为空项目
  bool empty() const { return type == PlayableType::Empty; }

  // 当前项目的类型，决定处理的方式
  PlayableType type;
  // 当前正在播放的动画的循环类型
  PlayMethod loop;

  // 播放的时间，会以Tick无限累加，然后通过这个时间来计算其它的Frame之类
  float time;

  // 当类型为Clip的时候，所使用的项目
  AnimationClip* clip;
  // 当类型为BlendTree的时候，所使用的项目
  AnimationBlend* blend;

  // 此项目的值，用于Blend的控制
  IVec2 value;

  // 一个空Playable
  static const Playable EMPTY;

private:
};

} // namespace ifire::game